# SvnFu class
# Copyright 2016 Florian Snow <florian@familysnow.net>
#
# This file is part of SVN Fakeupdate.
#
# SVN Fakeupdate is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''This module is merely a container for the class SvnFu.'''

import glob
import os
import re
import subprocess
import xml.etree.ElementTree


class SvnFu:
    '''Class for accessing the CLI SVN client and processing its output.

    Positional arguments:
    path --- the path of your SVN checkout directory

    Instance variables:
    self.path --- the path of your SVN checkout directory
    self.changed_files --- the set of changed files
    self.changed_english_files --- the set of changed English files
    aelf.files_to_change --- the set of files that need to be changed
    '''

    def __init__(self, path):
        self.path = path
        self.changed_files = self.get_changed_files_from_svn()
        self.changed_english_files = self.get_changed_english_files()
        self.files_to_change = self.get_files_to_change()

    def get_changed_files_from_svn(self):
        '''Return a set of changed files obtained from the CLI SVN client.'''
        changed_files = set()
        command = ['svn', 'status', '--xml', self.path]
        result = subprocess.check_output(command)
        xmltree = xml.etree.ElementTree.fromstring(result)
        for element in xmltree.iter('entry'):
            file_path = os.path.realpath(element.attrib['path'])
            changed_files.add(file_path)
        return changed_files

    def get_changed_english_files(self):
        '''Return a set of English files that have changed.'''
        pattern = re.compile('\.en\.x(ht){0,1}ml$', re.IGNORECASE)
        return {f for f in self.changed_files if re.search(pattern, f)}

    def get_files_to_change(self):
        '''Return a set of files that need to be changed.'''
        files_to_change = set()
        for f in self.changed_english_files:
            # the next line just replaces .en. with .*. starting from
            # the right
            glob_path = f[::-1].replace('.en.'[::-1], '.*.'[::-1], 1)[::-1]
            glob_result = glob.glob(glob_path)
            for entry in glob_result:
                if entry not in self.changed_files:
                    files_to_change.add(entry)
        return files_to_change

    def change_files(self):
        '''Insert/remove a newline at the top of all files to be changed.'''
        for f in self.files_to_change:
            fo = open(f, 'r')
            content = fo.readlines()
            fo.close()
            if re.search('^\s$', content[-1]):
                print('removing newline from', f)
                content = content[:-1]
            else:
                print('adding newline to', f)
                content = content + ['\n']
            fo = open(f, 'w')
            fo.writelines(content)
            fo.close()
